/**
 * Copyright &copy; 2012-2013 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.featherlike.feather.generator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.featherlike.feather.generator.config.ConfigProperties;
import com.featherlike.feather.generator.config.Constant;
import com.featherlike.feather.generator.db.DBKeyInfo;
import com.featherlike.feather.generator.db.MysqlKeyInfo;
import com.featherlike.feather.generator.engine.EngineFactory;
import com.featherlike.feather.generator.engine.ITemplateEngine;
import com.featherlike.feather.generator.entity.Column;
import com.featherlike.feather.generator.entity.Field;
import com.featherlike.feather.generator.entity.Table;
import com.featherlike.feather.generator.excel.ExcelContext;
import com.featherlike.framework.common.util.MapUtil;
import com.featherlike.framework.common.util.StringUtil;

/**
 * @author WYY
 * @description
 */
public class GeneratorImpl implements IGenerator {
	private static Logger logger = LoggerFactory.getLogger(GeneratorImpl.class);
	private GeneratorCfgImpl generatorCfg = GeneratorCfgImpl.instance();
	private ITemplateEngine tmplEngine = EngineFactory.getInstance()
			.getTemplateEngine(ConfigProperties.getTemlateEngine());

	// 数据库信息适配，如关键字、字段映射等
	private DBKeyInfo dbKeyInfo = MysqlKeyInfo.instance();

	private void generateSQL(Map<String, Object> dataMap) throws IOException {
		String tmplPath = Constant.TABLE + tmplEngine.getTemplateSuffix();
		String filePath = generatorCfg.getSqlPath(((Table) dataMap
				.get(Constant.KEY_TABLE)).getName());
		tmplEngine.mergeTemplateIntoFile(tmplPath, dataMap, filePath);
		logger.info("Table: {}", filePath);
	}

	private void generateJava(Map<String, Object> dataMap, String classType)
			throws IOException {
		String tmlpPath = classType + tmplEngine.getTemplateSuffix();
		String filePath = generatorCfg.getJavaPath(
				(String) dataMap.get(Constant.KEY_CLASSNAME), classType);
		tmplEngine.mergeTemplateIntoFile(tmlpPath, dataMap, filePath);
		logger.info("Java: {}", filePath);
	}

	private void generateView(Map<String, Object> dataMap, String viewType)
			throws IOException {
		String tmplPath = Constant.VIEW + viewType
				+ tmplEngine.getTemplateSuffix();
		String filePath = generatorCfg.getViewPath(
				(String) dataMap.get(Constant.KEY_CLASSNAME), viewType);
		tmplEngine.mergeTemplateIntoFile(tmplPath, dataMap, filePath);
		logger.info("View: {}", filePath);
	}

	private List<Map<String, Object>> getDataMaps(
			Map<Table, List<Column>> tableMap) {
		List<Map<String, Object>> dataMaps = new ArrayList<Map<String, Object>>();

		for (Map.Entry<Table, List<Column>> entry : tableMap.entrySet()) {
			Table table = entry.getKey();
			// 表名
			String tableName = table.getName();
			// 类名-首字母为小写
			String className = StringUtil.toCamelhump(tableName
					.substring(tableName.indexOf("_") + 1));

			List<Column> columnList = entry.getValue();
			List<Field> fieldList = transformFieldList(columnList);
			Map<String, Object> dataMap = MapUtil.newHashMap();

			dataMap.put(Constant.KEY_TABLE, table);
			dataMap.put("columnList", columnList);
			dataMap.put(Constant.KEY_CLASSNAME, className);
			dataMap.put("fieldList", fieldList);
			dataMap.put("StringUtil", new StringUtil());
			dataMap.putAll(generatorCfg.getModel(className));

			dataMaps.add(dataMap);
		}
		return dataMaps;
	}

	/**
	 * @description 生成所有文件
	 * @updated by WYY 2013年11月24日 下午3:41:36
	 * @param tableMap
	 * @throws IOException
	 */
	public void generateAll(Map<Table, List<Column>> tableMap)
			throws IOException {
		logger.info("--------------Generate start------------------");
		if (StringUtil.isBlank(generatorCfg.getPackageName())
				|| StringUtil.isBlank(generatorCfg.getModuleName())
				|| StringUtil.isBlank(generatorCfg.getFunctionName())) {
			logger.error("参数设置错误：包名、模块名、类名、功能名不能为空。");
			return;
		}
		List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
		for (Map<String, Object> dataMap : dataMaps) {
			// 生成Entity
			generateJava(dataMap, Constant.ENTITY);
			// 生成DAO
			generateJava(dataMap, Constant.DAO);
			// 生成Service
			generateJava(dataMap, Constant.SERVICE);
			// 生成Controller
			generateJava(dataMap, Constant.CONTROLLER);
			// 生成viewForm
			generateView(dataMap, Constant.VIEW_FORM);
			// 生成viewList
			generateView(dataMap, Constant.View_LIST);
			// 生成sql
			generateSQL(dataMap);
			logger.info("-----------------HLL-------------------------");
		}
		logger.info("------------Generate completely--------------");
	}

	public void generateAllSQL(Map<Table, List<Column>> tableMap)
			throws IOException {
		List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
		for (Map<String, Object> dataMap : dataMaps) {
			generateSQL(dataMap);
		}
	}

	public void generateAllJava(Map<Table, List<Column>> tableMap)
			throws IOException {
		List<Map<String, Object>> dataMaps = getDataMaps(tableMap);
		for (Map<String, Object> dataMap : dataMaps) {
			// 生成Entity
			generateJava(dataMap, Constant.ENTITY);
			// 生成DAO
			generateJava(dataMap, Constant.DAO);
			// 生成Service
			generateJava(dataMap, Constant.SERVICE);
			// 生成Controller
			generateJava(dataMap, Constant.CONTROLLER);
			// 生成viewForm
			generateView(dataMap, Constant.VIEW_FORM);
			// 生成viewList
			generateView(dataMap, Constant.View_LIST);
		}
	}

	private List<Field> transformFieldList(List<Column> columnList) {
		List<Field> fieldList = new ArrayList<Field>(columnList.size());
		for (Column column : columnList) {
			String fieldName = dbKeyInfo.transformFieldName(column.getName());
			String fieldType = dbKeyInfo.transformFieldType(column.getType());
			String fieldComment = column.getComment();
			String fieldLength = column.getLength();
			String listPage = column.getListPage();
			String queryPage = column.getQueryPage();
			String modifyPage = column.getModifyPage();
			String asLink = column.getAsLink();
			String dictType = column.getDictType();
			fieldList.add(new Field(fieldName, fieldType, fieldComment, Integer
					.parseInt(fieldLength), listPage, queryPage, modifyPage,
					asLink, dictType));
		}
		return fieldList;
	}

	public Map<Table, List<Column>> getTableMapFromExcel() {
		return ExcelContext.getInstance().getTableMapFromExcel(
				generatorCfg.getExcelPath());
	}

}
